using System;
using System.Runtime.InteropServices;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell.Interop;
using SolutionFactory.Exporter;
using SolutionFactory.UI;
using IServiceProvider=Microsoft.VisualStudio.OLE.Interop.IServiceProvider;

namespace SolutionFactory.Services
{
    public class IoC : IIoC
    {
        private readonly DTE2 _dte2;

        public IoC(DTE2 dte2)
        {
            _dte2 = dte2;
        }

        public IVsMonitorSelection MonitorSelection
        {
            get { return GetService<IVsMonitorSelection>(); }
        }

        public IVsOutputWindow OutputWindow
        {
            get { return GetService<IVsOutputWindow>(); }
        }

        #region IIoC Members

        public TInterface GetService<TInterface>()
        {
            return (TInterface) GetService(_dte2, typeof (TInterface).GUID);
        }

        public ExportGenerator CreateExportGenerator()
        {
            var messageBox = new MessageBox();
            var logger = new Logger(OutputWindow);
            var fileSystem = new FileSystem(logger);
            fileSystem.PostCopyVisitors.Add(new UncheckReadonlyVisitor(logger));
            fileSystem.PostCopyVisitors.Add(new RemoveTFSBindingsVisitor(logger));
			var fileTokenReplacer = new FileTokenReplacer(fileSystem);
			fileSystem.PostCopyVisitors.Add(new ReplaceSolutionNameWithTokens(logger, fileTokenReplacer));
            var templateInputController = new TemplateInputController(new TemplateInputView(), new MessageBox());
            var vsTemplateFactory = new VSTemplateFactory(fileSystem);
            var fileArchiveService = new FileArchiveService(logger);
            var fileCopyAndTokenReplacer = new FileCopyAndTokenReplacer(fileSystem, logger,
                                                                        new FileTokenReplacer(fileSystem));

            var installerCreationService = new InstallerCreationService(new ProcessExecutor(logger),
                                                                        new FileTokenReplacer(new FileSystem(logger)),
                                                                        new FileSystem(logger), logger);

            var solutionExporter = new SolutionExporter(fileSystem, messageBox, fileTokenReplacer,
                                                        vsTemplateFactory, logger, fileArchiveService,
                                                        fileCopyAndTokenReplacer, installerCreationService);
            return new ExportGenerator(
                (DTE) _dte2,
                fileSystem,
                messageBox, templateInputController,
                solutionExporter);
        }

        #endregion

        public object GetService(object serviceProvider, Guid guid)
        {
            object objService = null;

            IServiceProvider objIServiceProvider;

            IntPtr objIntPtr;

            int hr;

            Guid objSIDGuid;
            Guid objIIDGuid;
            objSIDGuid = guid;
            objIIDGuid = objSIDGuid;
            objIServiceProvider = (IServiceProvider) serviceProvider;
            hr = objIServiceProvider.QueryService(ref objSIDGuid, ref objIIDGuid, out objIntPtr);
            if (hr != 0)
            {
                Marshal.ThrowExceptionForHR(hr);
            }
            else if (!objIntPtr.Equals(IntPtr.Zero))
            {
                objService = Marshal.GetObjectForIUnknown(objIntPtr);
                Marshal.Release(objIntPtr);
            }
            return objService;
        }
    }
}